﻿using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System;
using System.Threading;
using NModbus.Device;
using NModbus;
using System.Net.Http;
using System.Linq;
using Sunny.UI;

public class ModbusClient
{
    
    private TcpClient tcpClient;

    private string ipAddress;
    private int port;
    private  IModbusMaster _modbusMaster;
    private readonly byte _slaveId;
    private bool _isConnected;
    private bool _closeTag;//
    public bool isConnected
    {
        get
        {
            return _isConnected && tcpClient.Connected;
        }
    }
    public ModbusClient(string ip, int port=502)
    {

        ipAddress = ip;
        this.port = port;

        _slaveId = 1;
        _closeTag = false;
    }
    ~ModbusClient()
    {
        Close();
    }
    public void Connect()
    {
        try
        {
            if (!_isConnected && tcpClient == null)
            {
                tcpClient = new TcpClient();
                
                tcpClient.SendTimeout = 3000;
                tcpClient.ReceiveTimeout = 3000;
                tcpClient.Connect(ipAddress, port);
                _isConnected = tcpClient.Connected;
                var factory = new ModbusFactory();
                _modbusMaster = factory.CreateMaster(tcpClient);
                
                // 设置超时（毫秒）
                _modbusMaster.Transport.ReadTimeout = 3000;
                _modbusMaster.Transport.WriteTimeout = 3000;
                
            }
        }
        catch (Exception ex)
        {
            Close();
            _isConnected = false;
        }
    }

    private void callBackConnect(IAsyncResult asyncresult)
    {
        if (tcpClient != null)
        {
            if (tcpClient.Connected)
                _isConnected = true;
            else
                _isConnected = false;
        }
    }

    public void ReConnect()
    {
        try
        {
            Task.Factory.StartNew(() =>
            {
                while (!_closeTag)
                {
                    Thread.Sleep( 1000);

                    if (tcpClient == null)
                    {
                        Connect();
                        continue;
                    }
                    
                    if (tcpClient.Client.Available <= 0)
                    {
                        if (tcpClient.Client.Poll(1, SelectMode.SelectRead))
                        {
                            // 已经断开连接了
                            Close();
                            Connect();
                        }                        

                        continue;
                    }

                    
                }

            }, TaskCreationOptions.LongRunning);
        }
        catch
        {
            _isConnected = false;
        }

    }


    public void Close()
    {
        if (tcpClient != null)
        {
            tcpClient.Close();
            tcpClient = null;
            _isConnected = false;
        }

    }

    #region 读取操作
    // 读取线圈（功能码01）
    public bool[] ReadCoils(ushort startAddr, ushort quantity)
    {
        return _modbusMaster.ReadCoils(_slaveId, startAddr, quantity);
    }

    // 读取保持寄存器（功能码03）
    public ushort[] ReadHoldingRegisters(ushort startAddr, ushort quantity)
    {
        return _modbusMaster.ReadHoldingRegisters(_slaveId, startAddr, quantity);
    }

    // 读取输入寄存器（功能码04）
    public ushort[] ReadInputRegisters(ushort startAddr, ushort quantity)
    {
        return _modbusMaster.ReadInputRegisters(_slaveId, startAddr, quantity);
    }
    #endregion

    #region 写入操作
    // 写入单个线圈（功能码05）
    public void WriteSingleCoil(ushort coilAddr, bool value)
    {
        _modbusMaster.WriteSingleCoil(_slaveId, coilAddr, value);
    }

    // 写入多个线圈（功能码15）
    public void WriteMultipleCoils(ushort startAddr, bool[] values)
    {
        _modbusMaster.WriteMultipleCoils(_slaveId, startAddr, values);
    }

    // 写入单个寄存器（功能码06）
    public void WriteSingleRegister(ushort regAddr, ushort value)
    {
        _modbusMaster.WriteSingleRegister(_slaveId, regAddr, value);
    }

    // 写入多个寄存器（功能码16）
    public void WriteMultipleRegisters(ushort startAddr, ushort[] values)
    {
        _modbusMaster.WriteMultipleRegisters(_slaveId, startAddr, values);
    }
    #endregion

    #region 高级扩展
    // 读取32位浮点数（大端序）
    public float ReadFloat(ushort startAddr)
    {
        var data = ReadHoldingRegisters(startAddr, 2);
        byte[] bytes = {
            (byte)(data[0] >> 8),
            (byte)data[0],
            (byte)(data[1] >> 8),
            (byte)data[1]
        };
        return BitConverter.ToSingle(bytes.Reverse().ToArray(), 0);
    }

    // 写入32位浮点数（大端序）
    public void WriteFloat(ushort startAddr, float value)
    {
        byte[] bytes = BitConverter.GetBytes(value).Reverse().ToArray();
        ushort[] registers = {
            (ushort)((bytes[0] << 8) | bytes[1]),
            (ushort)((bytes[2] << 8) | bytes[3])
        };
        WriteMultipleRegisters(startAddr, registers);
    }
    #endregion










}